Skip to content

Conversation

@LanceAdd
Copy link
Member

描述

此PR为gclient组件添加了增强的查询参数处理功能,支持通过结构体、映射、切片等多种数据类型设置查询参数,显著提升API使用的便捷性和类型安全性。

变更内容

1. Client结构体变更

  • Client结构体中添加了queryParams字段用于存储查询参数 (map[string]any)
  • New()函数中初始化queryParamsmake(map[string]any)
  • Clone()方法中添加queryParams的深拷贝逻辑

2. 配置方法新增 (gclient_config.go)

  • SetQuery: 设置单个查询参数
  • SetQueryMap: 批量设置查询参数
  • SetQueryParams: 通过结构体或映射设置查询参数

3. 链式调用方法新增 (gclient_chain.go)

  • Query: 通过映射设置查询参数
  • QueryParams: 通过结构体或映射设置查询参数
  • QueryPair: 设置单个查询参数

4. 请求处理逻辑增强 (gclient_request.go)

  • prepareRequest方法中添加查询参数处理逻辑
  • 使用url2 "net/url"包解析URL以避免命名冲突
  • 实现反射机制处理各种数据类型(基础类型、切片、数组等)
  • 添加对nil值和空切片的特殊处理
  • 实现查询参数与URL中已有参数的智能合并机制

API 描述

配置方法

  • SetQuery(key string, value any) *Client: 设置单个查询参数,支持任意类型值
  • SetQueryMap(m map[string]any) *Client: 批量设置查询参数,接受映射类型参数
  • SetQueryParams(params any) *Client: 设置查询参数,支持结构体、映射等类型,使用gconv.Map进行转换

链式调用方法

  • Query(m map[string]any) *Client: 通过映射设置查询参数,创建新的Client实例
  • QueryParams(params any) *Client: 通过结构体或映射设置查询参数,创建新的Client实例
  • QueryPair(key string, value any) *Client: 设置单个查询参数,创建新的Client实例

功能特性

1. 多数据类型支持

  • 基础类型:string, int, bool, float
  • 结构体:通过gconv.Map转换为映射
  • 映射:直接映射键值对(支持map[string]any
  • 切片类型:使用反射动态处理所有类型的切片,会转换为多个同名查询参数
  • 数组类型:使用反射动态处理所有类型的数组,会转换为多个同名查询参数
  • 空值处理:跳过显式的nil值和空切片

2. 智能参数合并

  • API设置的参数具有更高优先级
  • 自动处理键冲突和无冲突情况
  • 正确处理多值参数(通过queryValues.AddqueryValues.Set

3. 链式调用支持

  • 所有新方法都支持链式调用,符合gclient的设计风格

实现细节

prepareRequest方法中,查询参数处理的关键逻辑:

  • 解析当前请求URL以获取现有的查询参数
  • 遍历Client实例中的queryParams映射
  • 使用反射处理切片和数组类型,将其转换为多个同名参数
  • 对于普通值,直接设置为查询参数
  • 将处理后的查询参数编码并更新请求URL

使用示例

1. 基础使用

// 使用映射设置查询参数
client.Query(map[string]any{
    "page": 1,
    "size": 10,
    "sort": "created_at",
    "active": true,
}).Get(ctx, "http://example.com/api/users")

2. 结构体传参

// 定义查询参数结构体
type UserQuery struct {
    Page     int    `json:"page"`
    Size     int    `json:"size"`
    Sort     string `json:"sort"`
    Keyword  string `json:"keyword"`
}

// 使用结构体设置查询参数
params := UserQuery{Page: 1, Size: 20, Sort: "updated_at", Keyword: "golang"}
client.QueryParams(params).Get(ctx, "http://example.com/api/users")

3. 单个参数设置

// 设置单个查询参数
client.QueryPair("status", "active").Get(ctx, "http://example.com/api/users")

4. 链式调用

// 链式设置多个参数
client.QueryPair("status", "published").
    QueryPair("page", 1).
    QueryPair("featured", true).
    QueryPair("limit", 20).
    Get(ctx, "http://example.com/api/articles")

5. 切片和数组类型使用示例

// 使用字符串切片(会转换为多个同名查询参数)
client.Query(map[string]any{
    "tags": []string{"go", "programming", "web"},  // 生成 ?tags=go&tags=programming&tags=web
    "page": 1,
}).Get(ctx, "http://example.com/api/articles")

// 使用整数切片
client.Query(map[string]any{
    "ids": []int{1, 2, 3, 4},  // 生成 ?ids=1&ids=2&ids=3&ids=4
    "page": 1,
}).Get(ctx, "http://example.com/api/users")

// 使用各种数值类型切片
client.Query(map[string]any{
    "integers": []int32{10, 20, 30},     // 生成 ?integers=10&integers=20&integers=30
    "unsigned": []uint{1, 2, 3},       // 生成 ?unsigned=1&unsigned=2&unsigned=3
    "floats": []float32{1.1, 2.2, 3.3}, // 生成 ?floats=1.1&floats=2.2&floats=3.3
    "page": 1,
}).Get(ctx, "http://example.com/api/data")

6. 与其他配置组合使用

// 与其他客户端配置组合使用
client.SetHeader("Authorization", "Bearer token").
    Query(map[string]any{
        "page": 1,
        "size": 10,
    }).
    Get(ctx, "http://example.com/api/protected-data")

7. URL参数合并示例

// URL本身包含参数,与API设置的参数合并
// 原始URL: http://example.com/api/users?page=1&size=5
// 设置参数: client.Query(map[string]any{"page": 2, "sort": "name"})
// 最终URL: http://example.com/api/users?page=2&size=5&sort=name

向后兼容性

  • 完全向后兼容,不影响现有功能
  • 所有原有API继续正常工作
  • 不改变任何现有行为

性能考量

  • 查询参数存储在map中,内存开销可控
  • 参数处理在请求准备阶段完成,性能影响微小
  • 使用标准库的URL处理函数,效率高

- 新增 queryParams 字段用于存储查询参数映射
- 实现 Query、QueryParams 和 QueryPair 链式调用方法
- 添加 SetQuery、SetQueryMap 和 SetQueryParams 设置方法
- 支持结构体参数自动转换为查询参数
- 支持切片和数组类型的参数处理
- 实现 nil 值参数跳过逻辑
- 添加 URL 参数合并和覆盖功能
- 完善查询参数的单元测试覆盖
@gqcn gqcn added the awesome It's awesome! We keep watching. label Jan 21, 2026
@gqcn gqcn requested a review from Copilot January 21, 2026 11:22
@gqcn gqcn changed the title feat(net/gclient): Added query parameter handling function feat(net/gclient): added query parameter handling function Jan 21, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds comprehensive query parameter handling capabilities to the gclient HTTP client, enabling developers to set query parameters through multiple convenient methods using various data types including structs, maps, slices, and basic types.

Changes:

  • Added queryParams field to the Client struct to store query parameters
  • Implemented three configuration methods (SetQuery, SetQueryMap, SetQueryParams) and three chaining methods (Query, QueryParams, QueryPair)
  • Enhanced request preparation logic to process and merge query parameters with proper nil/empty value handling and type conversion using reflection

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
net/gclient/gclient.go Added queryParams field to Client struct, initialized in New(), and cloned in Clone() method
net/gclient/gclient_config.go Implemented SetQuery, SetQueryMap, and SetQueryParams configuration methods
net/gclient/gclient_chain.go Added Query, QueryParams, and QueryPair chaining methods for fluent API usage
net/gclient/gclient_request.go Enhanced prepareRequest with query parameter processing logic using reflection to handle slices/arrays and proper URL merging
net/gclient/gclient_z_unit_query_params_test.go Comprehensive test suite covering basic types, structs, slices/arrays, URL merging, chaining, special characters, and integration scenarios
net/gclient/gclient_z_unit_query_nil_test.go Extensive tests for nil value handling including nil pointers, nil slices, empty slices/arrays, and mixed scenarios

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

LanceAdd and others added 10 commits January 22, 2026 10:18
- 移除不必要的 url2 包导入
- 直接操作 URL 结构体字段而非重新解析 URL 字符串
- 提高高吞吐量应用的性能避免不必要的字符串操作
- 更新反射指针解引用注释说明完全解引用所有层级指针
- 简化查询参数编码直接设置到请求 URL 对象
- 新增mergeQueryParams函数统一处理URL查询参数合并
- 新增normalizeURL函数标准化URL前缀和协议
- 新增buildRequestParams函数构建请求参数
- 新增enhanceRequest函数增强请求上下文、头部和认证
- 新增createNormalPostRequest函数创建普通POST请求
- 新增createMultipartRequest函数创建多部分表单请求
- 新增createGetRequest函数创建GET请求并处理查询参数
- 新增createPostRequest函数创建POST/PUT/DELETE请求
- 优化prepareRequest函数结构化请求构建流程
- 改进参数处理优先级:queryParams > dataParams > urlParams
- 修复noUrlEncode标志对查询参数编码的影响
- 提升代码可读性和维护性
- 移除了单部分参数的空字符串赋值逻辑
- 添加了完整的查询参数与数据参数交互测试
- 验证了Query/QueryParams/QueryPair方法与Get方法数据参数的集成
- 确保查询参数优先级高于数据参数
- 测试了多种参数类型的组合场景
- 移除 unused empty 包依赖
- 在 SetQueryParam 方法中过滤 nil 值以保持一致性
- 在 SetQueryParams 方法中过滤 nil 值以保持一致性
- 简化 IsNil 检查逻辑直接使用 != nil 判断
- 新增GetMergedURL方法用于获取合并后的URL而不发送请求
- 添加GetMergedURL单元测试验证不同HTTP方法的行为
- 完善所有HTTP方法的查询参数功能测试
- 支持结构体、切片、数组等多种查询参数类型
- 实现查询参数与URL参数的合并逻辑
- 添加查询参数与请求体数据的组合测试
- 新增GetBodyMap方法仅获取请求体参数
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awesome It's awesome! We keep watching.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants